# 5.5 The Unique Db Record Mode

# 1. Common Usage

The Db class, along with its accompanying Record class, offers a richer set of database operation functionalities outside the Model class. When using the Db and Record classes, there's no need for mapping to the database table, as Record acts as a generic Model. Here's some common usage of the Db + Record mode:

// Create a record object with name attribute as James and age attribute as 25 and add it to the database
Record user = new Record().set("name", "James").set("age", 25);
Db.save("user", user);

// Delete the record with id value 25 from the user table
Db.deleteById("user", 25);

// Find the record with id value 25, change its name attribute to James, and update it in the database
user = Db.findById("user", 25).set("name", "James");
Db.update("user", user);

// Get the name attribute of the user
String userName = user.getStr("name");
// Get the age attribute of the user
Integer userAge = user.getInt("age");

// Find all users older than 18
List<Record> users = Db.find("select * from user where age > 18");

// Paginate and find users older than 18, current page number is 1, and each page has 10 users
Page<Record> userPage = Db.paginate(1, 10, "select *", "from user where age > ?", 18);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

Here's an example of transaction processing:

boolean succeed = Db.tx(new IAtom() {
    public boolean run() throws SQLException {
        int count = Db.update("update account set cash = cash - ? where id = ?", 100, 123);
        int count2 = Db.update("update account set cash = cash + ? where id = ?", 100, 456);
        return count == 1 && count2 == 1;
    }
});
1
2
3
4
5
6
7

Both database updates above are executed in a single transaction. If any exception occurs during execution or if the run() method returns false, the transaction will automatically roll back.

# 2. Db.query(...)

When there's only one field after the select in the SQL, an appropriate generic can be used to receive data:

List<String> titleList = Db.query("select title from blog");
1

For SQL that has more than one field after select, you must use List<Object[]> to receive data:

List<Object[]> list = Db.query("select id, title, content from blog");
List<Object[]> list = Db.query("select * from blog");
1
2

# 3. Db.queryXxx(...)

The Db.queryXxx series of methods, like queryInt, queryLong, and queryStr, are very convenient for SQL with aggregate functions:

int total = Db.queryInt("select count(*) from account");
1

Besides aggregate functions, you can also use it to query a specific field value of a record:

String nickName = Db.queryStr("select nickName from account where id = ? limit 1", 123);
1

# 4. The Difference Between Db.find(...) Series and Db.query(...)/Db.queryXxx(...) Series

The former always wraps the return value into a Record object, while the latter returns the data as is without wrapping.

# 5. Extending Db Functionality

All functionalities of the Db utility class rely on the underlying DbPro. DbPro can be customized via inheritance to add desired functionalities:

public class MyDbPro extends DbPro {
    public MyDbPro(String configName) {
        super(configName);
    }

    public List<Record> find(String sql, Object... paras) {
        System.out.println("Sql: " + sql);
        System.out.println("Paras: " + Arrays.toString(paras));
        return super.find(sql, paras);
    }
}
1
2
3
4
5
6
7
8
9
10
11

After defining your custom DbPro class, you can configure it to override the behavior of the default DbPro:

ActiveRecordPlugin arp = new ActiveRecordPlugin(...);
arp.setDbProFactory(configName -> new MyDbPro(configName));
1
2

Through this method, you can replace, enhance, or change the behavior of all public and protected methods in DbPro. It's a very flexible and convenient approach.

Last Updated: 9/17/2023, 6:16:57 AM